package db

import (
	"fmt"
	"go-base/src/configs"
	"go-base/src/logs"
	"gopkg.in/mgo.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"os"
	"time"
)

var (
	mGrom     *gorm.DB
	con       = configs.Conf
	mMGO      *mgo.Session
	mongoName string
)

//数据库初始化
func Init() {
	//mysqlInit()
	mongoInit(con.DbName, con.MongoHost, con.MongoUser, con.MongoPass)
}

//mysql初始化
func mysqlInit() {
	dbName := con.DbName
	dsn := fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=%s&parseTime=True&loc=%s", con.DbUsername, con.DbPassword, con.DbHost, con.DbPort, dbName, con.DbCharset, con.TimeZone)
	masterConfig := mysql.New(mysql.Config{
		DSN:                       dsn,
		DefaultStringSize:         1024,  // string 类型字段的默认长度
		DisableDatetimePrecision:  true,  // 禁用 datetime 精度，MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式，MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,  // 用 `change` 重命名列，MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	})
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold: time.Second, // 慢 SQL 阈值
			LogLevel:      logger.Info, // Log level
			Colorful:      true,        // 禁用彩色打印
		},
	)
	//gorm连接数据库
	db, err := gorm.Open(masterConfig, &gorm.Config{
		Logger: newLogger,
	})
	db.Debug()
	if err != nil {
		logs.Error.Printf("init gorm err:%v\n", err)
		return
	}
	s, err := db.DB()
	if err != nil {
		logs.Error.Printf("init gorm err:%v\n", err)
		return
	}
	s.SetMaxIdleConns(int(con.MaxIdleConns))
	s.SetMaxOpenConns(int(con.MaxOpenConns))
	logs.Info.Println("gorm init success!!!")
	mGrom = db
}

//mongo初始化
func mongoInit(dbName, url, user, pass string) {
	mongoName = dbName
	var err error
	for {
		<-time.After(time.Second)
		if mMGO == nil {
			logs.Info.Println("开始连接mongo...")
			mMGO, err = mongoConnect(url, user, pass)
			if err != nil {
				continue
			}
			logs.Error.Println("连接mongo成功...")
			break
		}
	}
	go func() {
		for {
			<-time.After(time.Second)
			if err = mMGO.Ping(); err != nil {
				db, err := mongoConnect(url, user, pass)
				if err != nil {
					logs.Error.Printf("重连mongo [%v] [%v] 失败! %v", url, user, err)
					continue
				}

				mMGO = db
				logs.Info.Println("重连mongo成功!!")
			}
		}
	}()
}

//连接mongo
func mongoConnect(url, user, pass string) (*mgo.Session, error) {
	db, err := mgo.Dial(url)
	if err != nil {
		return nil, err
	}
	//用户登录
	if user != "" {
		err = db.Login(&mgo.Credential{
			Username: user,
			Password: pass,
		})
		if err != nil {
			return nil, err
		}
	}
	return db, nil
}

//获取gorm对象
func GetMysql() *gorm.DB {
	return mGrom
}

//获取mongo对象
func GetMongo() *mgo.Database {
	return mMGO.DB(mongoName)
}
